package com.zhou.bjgl.bjgl.business_web.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.zhou.bjgl.bjgl.business_web.entity.BCourse;
import com.zhou.bjgl.bjgl.business_web.entity.BSigning;
import com.zhou.bjgl.bjgl.business_web.service.BCourseService;
import com.zhou.bjgl.bjgl.exception.BwException;
import com.zhou.bjgl.bjgl.exception.BwExceptionEnum;
import com.zhou.bjgl.bjgl.business_web.mapper.BCourseMapper;
import com.zhou.bjgl.bjgl.business_web.mapper.BSigningMapper;
import com.zhou.bjgl.bjgl.req.b_course.BCourseQueryReq;
import com.zhou.bjgl.bjgl.req.b_sign.BSigningChartsReq;
import com.zhou.bjgl.bjgl.req.b_sign.BSigningQueryReq;
import com.zhou.bjgl.bjgl.resp.BCourseResp;
import com.zhou.bjgl.bjgl.resp.sgin.BSigningResp;
import com.zhou.bjgl.bjgl.resp.PageResp;
import com.zhou.bjgl.bjgl.business_web.service.BSigningService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhou.bjgl.bjgl.util.CopyUtil;
import com.zhou.bjgl.bjgl.util.DateUtil;
import org.apache.poi.ss.formula.functions.T;
import org.gavaghan.geodesy.Ellipsoid;
import org.gavaghan.geodesy.GeodeticCalculator;
import org.gavaghan.geodesy.GeodeticCurve;
import org.gavaghan.geodesy.GlobalCoordinates;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * <p>
 *  签到servcie实现类
 * </p>
 *
 * @author jz
 * @since 2021-07-04
 */
@Service
public class BSigningServiceImpl extends ServiceImpl<BSigningMapper, BSigning> implements BSigningService {


    @Resource
    private BCourseMapper bCourseMapper;

    @Resource
    private BSigningMapper bSigningMapper;

    @Resource
    private BCourseService bCourseService;

    /**
     * 获取签到列表
     * @param req
     * @return
     */
    @Override
    public PageResp<BSigningResp> getCheckList(BSigningQueryReq req) {

        PageHelper.startPage(req.getPage(),req.getSize());
        List<BSigningResp> bSigningResps=bSigningMapper.queryCheckList(req);

        PageResp<BSigningResp> bSigningRespPageResp = new PageResp<>();

        PageInfo<BSigningResp> bSigningRespPageInfo = new PageInfo<>(bSigningResps);

        bSigningRespPageResp.setTotal(bSigningRespPageInfo.getTotal());
        bSigningRespPageResp.setPageList(bSigningResps);
        return bSigningRespPageResp;
    }

    /**
     *  用于学生的课堂签到
     * @param req
     */
    @Override
    public void checkInClass(BSigningQueryReq req) {
        QueryWrapper<BCourse> bCourseQueryWrapper = new QueryWrapper<>();
        bCourseQueryWrapper.eq("course_code",req.getCourseCode());
        BCourse bCourse = bCourseMapper.selectOne(bCourseQueryWrapper);
        if (bCourse == null) {
            throw new BwException(BwExceptionEnum.CODE_NOT_EXIST);
        }
        if(bCourse.getStatus()!=null&&bCourse.getStatus()==1){
            throw new BwException(BwExceptionEnum.CODE_OVERDUE);
        }
        //检查是否已经签到
        QueryWrapper<BSigning> bSigningQueryWrapper = new QueryWrapper<>();
        bSigningQueryWrapper.eq("course_code",req.getCourseCode()).eq("student_id",req.getStudentId());
        BSigning bSigning = bSigningMapper.selectOne(bSigningQueryWrapper);
        if (bSigning != null) {
            throw new BwException(BwExceptionEnum.ALREADLY_CHECK);
        }

        //进行位置范围判断
        Double latitudeInApply = bCourse.getLatitude();
        Double longitudeInApply = bCourse.getLongitude();

        //构造两个地理坐标点
        GlobalCoordinates source = new GlobalCoordinates(latitudeInApply, longitudeInApply);
        GlobalCoordinates target = new GlobalCoordinates(req.getLatitude(), req.getLongitude());

        //传入两个坐标和距离计算方式
        double distanceMeter = getDistanceMeter(source, target, Ellipsoid.Sphere);
        //如果距离打开地点远于100m，打卡失败
        if (distanceMeter > 500) {
            throw new BwException(BwExceptionEnum.OUT_OF_POSITION);
        }

        //把请求对象复制到实体对象
        BSigning signing = CopyUtil.copy(req, BSigning.class);
        bSigningMapper.insert(signing);
    }

    /**
     * 计算两点之间距离的方法
     * @param gpsFrom
     * @param gpsTo
     * @param ellipsoid
     * @return
     */
    public static double getDistanceMeter(GlobalCoordinates gpsFrom, GlobalCoordinates gpsTo, Ellipsoid ellipsoid)
    {
        //创建GeodeticCalculator，调用计算方法，传入坐标系、经纬度用于计算距离
        GeodeticCurve geoCurve = new GeodeticCalculator().calculateGeodeticCurve(ellipsoid, gpsFrom, gpsTo);

        return geoCurve.getEllipsoidalDistance();
    }
    @Override
    public PageResp<BSigningResp> getNotCheckList(BSigningQueryReq req) {

        PageHelper.startPage(req.getPage(),req.getSize());
        List<BSigningResp> bSigningResps=bSigningMapper.queryNotCheckList(req);

        PageResp<BSigningResp> bSigningRespPageResp = new PageResp<>();

        PageInfo<BSigningResp> bSigningRespPageInfo = new PageInfo<>(bSigningResps);

        bSigningRespPageResp.setTotal(bSigningRespPageInfo.getTotal());
        bSigningRespPageResp.setPageList(bSigningResps);
        return bSigningRespPageResp;
    }

    @Override
    public HashMap<String, List> getChartsDate(BSigningChartsReq bSigningChartsReq) {

        //用于存储每个所需字段的的数据
        HashMap<String, List> rsultMap = new HashMap<>(4);
        //获取所有日期
        List<String> betweenDate;
        if (ObjectUtils.isEmpty(bSigningChartsReq.getStartDate())) {
            betweenDate = DateUtil.getLastWeek();
        } else {
            betweenDate = DateUtil.getBetweenDate(bSigningChartsReq.getStartDate(), bSigningChartsReq.getEndDate());
        }

        rsultMap.put("dateList",betweenDate);
        //构建查询对象
        BSigningChartsReq bSigningChartsReqQuery = new BSigningChartsReq();
        bSigningChartsReqQuery.setClassId(bSigningChartsReq.getClassId());
        //遍历每个日期的数据
        ArrayList<Integer> resultCountList = new ArrayList<>();
        BCourseQueryReq bCourseQueryReq = new BCourseQueryReq();
        bCourseQueryReq.setClassId(bSigningChartsReq.getClassId());
        bCourseQueryReq.setPage(0);
        bCourseQueryReq.setSize(1);

        for (String date:
             betweenDate) {
            int all=0;
            List<BCourseResp> bCourseResps = bCourseMapper.queryCourseList(bCourseQueryReq.setCreateDate(date));
            for (BCourseResp bc:
                    bCourseResps) {
                bSigningChartsReqQuery.setStartDate(date);
                int count=bSigningMapper.queryNotCheckForDate(bSigningChartsReqQuery.setCourseCode(bc.getCourseCode()));
                all+=count;
            }
            resultCountList.add(all);
        }
        //用于存储每个所需字段的的数据
        rsultMap.put("countList", resultCountList);
        return rsultMap;
    }
}
